const std = @import("std");
const protocol = @import("protocol");
const Session = @import("../Session.zig");
const Packet = @import("../Packet.zig");
const Config = @import("config.zig");
const Data = @import("../data.zig");
const ChallengeData = @import("challenge.zig");
const BattleManager = @import("../manager/battle_mgr.zig").BattleManager;
const ChallegeStageManager = @import("../manager/battle_mgr.zig").ChallegeStageManager;
const NodeCheck = @import("../commands/value.zig");

const ArrayList = std.ArrayList;
const Allocator = std.mem.Allocator;
const CmdID = protocol.CmdID;

pub var on_battle: bool = false;

pub fn onStartCocoonStage(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.StartCocoonStageCsReq, allocator);
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    on_battle = true;
    try session.send(CmdID.CmdStartCocoonStageScRsp, protocol.StartCocoonStageScRsp{
        .retcode = 0,
        .cocoon_id = req.cocoon_id,
        .prop_entity_id = req.prop_entity_id,
        .wave = req.wave,
        .battle_info = battle,
    });
}
pub fn onQuickStartCocoonStage(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.QuickStartCocoonStageCsReq, allocator);
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    on_battle = true;
    try session.send(CmdID.CmdQuickStartCocoonStageScRsp, protocol.QuickStartCocoonStageScRsp{
        .retcode = 0,
        .cocoon_id = req.cocoon_id,
        .wave = req.wave,
        .battle_info = battle,
    });
}
pub fn onQuickStartFarmElement(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.QuickStartFarmElementCsReq, allocator);
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    on_battle = true;
    try session.send(CmdID.CmdQuickStartFarmElementScRsp, protocol.QuickStartFarmElementScRsp{
        .retcode = 0,
        .world_level = req.world_level,
        .JDANOKNHNHL = req.JDANOKNHNHL,
        .battle_info = battle,
    });
}
pub fn onStartBattleCollege(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.StartBattleCollegeCsReq, allocator);
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    on_battle = true;
    try session.send(CmdID.CmdStartBattleCollegeScRsp, protocol.StartBattleCollegeScRsp{
        .retcode = 0,
        .id = req.id,
        .battle_info = battle,
    });
}
pub fn onSceneCastSkill(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    var challege_mgr = ChallegeStageManager.init(allocator);
    const challenge = try challege_mgr.createChallegeStage();
    const req = try packet.getProto(protocol.SceneCastSkillCsReq, allocator);
    var monster_battle_info_list = ArrayList(protocol.HitMonsterBattleInfo).init(allocator);
    try monster_battle_info_list.appendSlice(&[_]protocol.HitMonsterBattleInfo{
        .{
            .target_monster_entity_id = 0,
            .monster_battle_type = protocol.MonsterBattleType.MONSTER_BATTLE_TYPE_TRIGGER_BATTLE,
        },
    });

    var battle_info: ?protocol.SceneBattleInfo = null;

    if (req.assist_monster_entity_id_list.items.len > 0 or
        (req.attacked_by_entity_id >= 1 and req.attacked_by_entity_id <= 99))
    {
        if (ChallengeData.on_challenge) {
            battle_info = challenge;
        } else {
            battle_info = battle;
            on_battle = true;
        }
    }

    try session.send(CmdID.CmdSceneCastSkillScRsp, protocol.SceneCastSkillScRsp{
        .retcode = 0,
        .cast_entity_id = req.cast_entity_id,
        .monster_battle_info = monster_battle_info_list,
        .battle_info = battle_info,
    });
}

pub fn onGetCurBattleInfo(session: *Session, _: *const Packet, allocator: Allocator) !void {
    var battle_mgr = BattleManager.init(allocator);
    const battle = try battle_mgr.createBattle();
    var challege_mgr = ChallegeStageManager.init(allocator);
    const challenge = try challege_mgr.createChallegeStage();

    var rsp = protocol.GetCurBattleInfoScRsp.init(allocator);
    rsp.battle_info = if (ChallengeData.on_challenge == true) challenge else if (on_battle == true) battle else null;
    rsp.retcode = 0;
    try session.send(CmdID.CmdGetCurBattleInfoScRsp, rsp);
}

pub fn onPVEBattleResult(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.PVEBattleResultCsReq, allocator);
    var rsp = protocol.PVEBattleResultScRsp.init(allocator);
    rsp.battle_id = req.battle_id;
    rsp.end_status = req.end_status;
    rsp.stage_id = req.stage_id;
    on_battle = false;
    try session.send(CmdID.CmdPVEBattleResultScRsp, rsp);
}

pub fn onSceneCastSkillCostMp(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.SceneCastSkillCostMpCsReq, allocator);
    try session.send(CmdID.CmdSceneCastSkillCostMpScRsp, protocol.SceneCastSkillCostMpScRsp{
        .retcode = 0,
        .cast_entity_id = req.cast_entity_id,
    });
}

pub fn onSyncClientResVersion(session: *Session, packet: *const Packet, allocator: Allocator) !void {
    const req = try packet.getProto(protocol.SyncClientResVersionCsReq, allocator);
    std.debug.print("CLIENT RES VERSION: {}\n", .{req.client_res_version});
    try session.send(CmdID.CmdSyncClientResVersionScRsp, protocol.SyncClientResVersionScRsp{
        .retcode = 0,
        .client_res_version = req.client_res_version,
    });
}
